﻿/* Filename: Map.as 
 *
 * Description: This class can be used to make a map of
 * tiles on screen.  The map is stored as a two-dimensional
 * array of Tile objects.
 *
 * Note: Maps should have access to 100 depths, starting with
 * the one passed in as a parameter when the map is drawn.
 *
 * Tyler Samson
 * Feb 2008
 * @ Sierra Nevada College
 */
class Map {
	
	//*** Map Settings ***//
	private var _mapName:String;		// name of map
	private var _mapWidth:Number;		// width of the map in tiles
	private var _mapHeight:Number;		// height of the map in tiles
	private var _tileWidth:Number;		// width of tiles in pixels
	private var _tileHeight:Number;		// height of tiles in pixels
	public var _mapArray:Array;		// array of Tile objects that makeup the map
	
	//*** Map Visual Settings ***//
	private var _mapDepth:Number;		// depth of map on screen
	private var _mapX:Number;			// horizontal location of map
	private var _mapY:Number;			// vertical location of map
	
	private var _demonsDepth:Number;			// base depth of demons on the map
	private var _selectorTargetDepth:Number;	// base depth of target selectors
	private var _selectorDepth:Number;			// depth of selector icon on screen
	
	public function Map(p_mapName:String, p_mapWidth:Number,
						p_mapHeight:Number, p_tileWidth:Number,
						p_tileHeight:Number, p_tileTypes:Array) {
		
		_mapName = p_mapName;
		_mapWidth = p_mapWidth;
		_mapHeight = p_mapHeight;
		_tileWidth = p_tileWidth;
		_tileHeight = p_tileHeight;
		_mapArray = new Array();
		
		for (var i = 0; i < p_mapWidth; i++) {
			var _verticalArray:Array = new Array();
			
			for (var j = 0; j < p_mapHeight; j++) {
				var _randomType:Number = Math.floor(Math.random()*p_tileTypes.length);
				var _tileType:String = p_tileTypes[_randomType];
				var _tileName:String = "tileX" + i + "Y" + j;						// create the name for the tile
				var _tileX = i;														// give the tile its X location
				var _tileY = j;														// give the tile its Y location
				var _tile:Tile = new Tile(_tileName, _tileType, _tileX, _tileY);	// create the next tile
				_verticalArray.push(_tile);
			}
			
			_mapArray.push(_verticalArray);
		}
	}
	
	// output all map information to standard out
	public function outputMap():Void {
		trace("MAP: " + _mapName +  "\n\tWidth: " + _mapWidth +
			  "  Height: " + _mapHeight + "\n\t" + 
			  "  TileWidth: " + _tileWidth + "\n\t" + 
			  "  TileHeight: " + _tileHeight);
		trace("\t" + mapArrayToString());
	}
	
	// change mapArray to a String for output
	public function mapArrayToString():String {
		var _mapString:String = "Map Array:\n\t";					// return array

		for(var i = 0; i < _mapHeight; i++) {					// step through outer array
			for (var j = 0; j < _mapWidth; j++) {				// step through inner array
				var _num = _mapArray[j][i].getElementType();	// find number of tile object at [i][j]
				_mapString = _mapString.concat("\t", _num);			// add to output array
			}
			
			_mapString = _mapString.concat(" ", "\n\t");			// add new line to differentiate inner from outer arrays
		}
		
		return _mapString;
	}
	
	// draw the map on screen
	public function drawMap(p_mapDepth:Number, p_demonsDepth:Number, p_mapX:Number, p_mapY:Number):Void {
		trace("start map");
		
		_mapDepth = p_mapDepth;
		_mapX = p_mapX;
		_mapY = p_mapY;
		
		_demonsDepth = p_demonsDepth;
		_selectorTargetDepth = p_mapDepth + (_mapWidth*_mapHeight);
		_selectorDepth = _selectorTargetDepth + (_mapWidth*_mapHeight);
		
		for (var i = 0; i < _mapWidth; i++) {							// step through each array in _mapArray
			for (var j = 0; j < _mapHeight; j++) {						// step through each tile in inner arrays
				var _depth:Number = p_mapDepth + (j * _mapWidth) + i;	// create depth
				var _tile:Tile = _mapArray[i][j];
				drawTile(_tile, _depth);								// draw the tile
				
				if (_tile.getDemon()) {												// evaluates to true if the tile contains a demon
					var _demonDepth:Number = _demonsDepth + (j * _mapWidth) + i;	// create depth
					drawDemon(_tile.getDemon(), _demonDepth);						// draw the demon on screen
				}
			}
		}
		
		trace("end map");
	}
	
	public function pixelToTileX(p_x:Number):Number {
		return _mapX + _tileWidth*p_x;	// calculate horizontal location
	}
	
	public function pixelToTileY(p_y:Number):Number {
		return _mapY + _tileHeight*p_y;	// calculate vertical location
	}
	
	// draw a tile on screen
	public function drawTile(p_tile:Tile, p_depth:Number):Void {
		var _tileName = _mapName + p_tile.getName();			// create a name specific to the map and tile
		var _xLocation:Number = pixelToTileX(p_tile.getX());	// calculate horizontal location
		var _yLocation:Number = pixelToTileY(p_tile.getY());	// calculate vertical location
		var _map:Map = this;									// set _map to "this" to pass to tile functions
		
		Graphics.loadAndDrawObject(_tileName, p_depth,
								   p_tile.graphicName(),
								   _xLocation, _yLocation);
		
		if (p_tile.getCounter() >= 0) {
			_root[_tileName].createEmptyMovieClip("counterBG", 2);
			_root[_tileName]["counterBG"].loadMovie("tiles/tileCounter.png");
			_root[_tileName].createEmptyMovieClip("counterText", 3);
			_root[_tileName]["counterText"]._x = 58;
			_root[_tileName]["counterText"]._y = 70;
			_root[_tileName]["counterText"].createTextField("counter", 1, 0, 0, 50, 40);
			_root[_tileName]["counterText"].counter.text = p_tile.getCounter();
		
			var _counterTextFormat:TextFormat = 
				new TextFormat("Impact", 16, 0xFDAB02, false, false, false, null, null, "center");
			_root[_tileName]["counterText"].counter.setTextFormat(_counterTextFormat);
		}
		
		_root[_tileName].onRelease = function () {
			BattleController.tileOnPress(p_tile);
		}
		
		_root[_tileName].onRollOver = function () {
			//_map.select(p_tile.getX(), p_tile.getY());
			BattleController.tileOnOver(_map, p_tile);
		}
		
		/*
		 * The following is used to see depths of tiles.  loadMovie in Graphics
		 * must be commented out for this to work because the loaded tile disables
		 * the text.
		 *	_root[_tileName][_tileName + "I"].createTextField([_tileName + "DepthText"], 2000 + p_depth, 1, 1, 100, 100);
		 *	_root[_tileName][_tileName + "I"][_tileName + "DepthText"].text = "Depth = " + p_depth;
		 */
	}
	
	public function decrementTiles() {
		for (var i = 0; i < this._mapWidth; i++) {
			for (var j = 0; j < this._mapHeight; j++) {
				var _xLocation:Number = pixelToTileX(i);
				var _yLocation:Number = pixelToTileY(j);	
				var _thisCounter:Number = this._mapArray[i][j].getCounter();
				
				if (_thisCounter > 0) {
					this._mapArray[i][j].setCounter(_thisCounter - 1);
					redrawTile(this._mapArray[i][j]);
				} else if (_thisCounter != -1) {
					this._mapArray[i][j].resetTileType();
					this._mapArray[i][j].setCounter(-1);
					redrawTile(this._mapArray[i][j]);
				}
			}
		}
	}
	
	public function redrawTile(p_tile:Tile) {
		var _depth:Number = _mapDepth + (p_tile.getY() * _mapWidth) + p_tile.getX();	// create depth
		drawTile(p_tile, _depth);
	}
	
	public function getColumn(p_x:Number):Array {
		return _mapArray[p_x];
	}
	
	public function getRow(p_y:Number):Array {
		var _returnTiles = new Array();
		for (var i = 0; i < _mapArray.length; i++) {
			_returnTiles.push(_mapArray[i][p_y]);
		}
		return _returnTiles;
	}
	
	public function getTile(p_x:Number, p_y:Number):Tile {
		return _mapArray[p_x][p_y];
	}
	
	public function drawDemon(p_demon:Demon, p_depth:Number) {
		var _demonName = _mapName + p_demon.getName();			// create a name specific to the map and tile
		var _xLocation:Number = pixelToTileX(p_demon.getX());	// calculate horizontal location
		var _yLocation:Number = pixelToTileY(p_demon.getY());	// calculate vertical location
		
		Graphics.loadAndDrawObject(_demonName, p_depth,
								   p_demon.graphicName(),
								   _xLocation, _yLocation);
	}
	
	// add demons to the map
	public function addDemons(p_demons:Array):Void {
		for (var i = 0; i < p_demons.length; i++) {
			addDemon(p_demons[i]);
		}
	}
	
	// add demon to the map by adding to the tile on the map
	public function addDemon(p_demon:Demon):Void {
		_mapArray[p_demon.getX()][p_demon.getY()].addDemon(p_demon);
	}
	
	public function removeDemon(p_demon:Demon):Void {
		var _demonName = _mapName + p_demon.getName();			// create a name specific to the map and tile
		
		removeMovieClip(_demonName);
	}
	
	public function redrawDemon(p_tileNew:Tile):Void {
		removeDemon(p_tileNew.getDemon());
		var _demonDepth:Number = _demonsDepth +
					(p_tileNew.getY() * _mapWidth) + p_tileNew.getX();	// create depth
		drawDemon(p_tileNew.getDemon(), _demonDepth);					// draw the demon on screen
	}
	
	// Returns the demon on the tile, if the tile contains one
	public function getDemon(p_x:Number, p_y:Number):Demon {
		return _mapArray[p_x][p_y].getDemon();
	}
	
	public function selectDemon(p_x:Number, p_y:Number):Void {
		//trace(_selectorDepth + "x" + p_x + "Y" + p_y);
		var _xLocation:Number = pixelToTileX(p_x);	// calculate horizontal location
		var _yLocation:Number = pixelToTileY(p_y);	// calculate vertical location
		var _graphicName:String = "menus/selectorDemon.swf";
		
		removeSelector();							// remove the selector so that the old one does not conflict with the new one
		Graphics.loadAndDrawObject("selector", _selectorDepth, _graphicName, _xLocation, _yLocation);
	}
	
	public function selectTargetDemons(p_x:Number, p_y:Number, p_type:String):Void {
		//trace(_selectorDepth + "x" + p_x + "Y" + p_y);
		var _xLocation:Number = pixelToTileX(p_x);	// calculate horizontal location
		var _yLocation:Number = pixelToTileY(p_y);	// calculate vertical locationvar
		var _depth:Number = _selectorTargetDepth + (p_y * _mapWidth) + p_x;	// create depth
		var _graphicName:String = "menus/selectorTarget" + p_type + ".swf";

		this._mapArray[p_x][p_y].setIsTarget(true);
		
		removeSelector();							// remove the selector so that the old one does not conflict with the new one
		Graphics.loadAndDrawObject("selectorTarget" + _depth , _depth, _graphicName, _xLocation, _yLocation);
	}
	
	public function selectMovementTiles(p_x:Number, p_y:Number, p_movement:Number):Void {
		var _graphicName:String = "menus/selectorMovement.swf";
		
		for (var i = 0; i < this._mapWidth; i++) {
			var _xLocation:Number = pixelToTileX(i);	// calculate horizontal location
			var _yLocation:Number = pixelToTileY(p_y);	// calculate vertical locationvar
			var _depth:Number = _selectorTargetDepth + (p_y * _mapWidth) + i;	// create depth
			var _difference = Math.abs(i - p_x);
			
			if (_difference <= p_movement && _difference != 0 && !getDemon(i, p_y)) {
				this._mapArray[i][p_y].setIsTarget(true);
				Graphics.loadAndDrawObject("selectorTarget" + _depth , _depth, _graphicName, _xLocation, _yLocation);
			}
		}
		
		for (var j = 0; j < this._mapHeight; j++) {
			var _xLocation:Number = pixelToTileX(p_x);	// calculate horizontal location
			var _yLocation:Number = pixelToTileY(j);	// calculate vertical locationvar
			var _depth:Number = _selectorTargetDepth + (j * _mapWidth) + p_x;	// create depth
			var _difference = Math.abs(j - p_y);
			
			if (_difference <= p_movement && _difference != 0 && !getDemon(p_x, j)) {
				this._mapArray[p_x][j].setIsTarget(true);
				Graphics.loadAndDrawObject("selectorTarget" + _depth , _depth, _graphicName, _xLocation, _yLocation);
			}
		}
	}
	
	public function selectTilesOpenToChange() {
		var _graphicName:String = "menus/selectorTerrain.swf";
		
		for (var i = 0; i < this._mapWidth; i++) {
			for (var j = 0; j < this._mapHeight; j++) {
				var _xLocation:Number = pixelToTileX(i);
				var _yLocation:Number = pixelToTileY(j);	
				var _depth:Number = _selectorTargetDepth + (j * _mapWidth) + i;
				
				if (this._mapArray[i][j].getCounter() == -1) {
					this._mapArray[i][j].setIsTarget(true);
					Graphics.loadAndDrawObject("selectorTarget" + _depth , _depth, _graphicName, _xLocation, _yLocation);
				}
			}
		}
	}
	
	public function selectTilesOpenShape(p_tile:Tile, p_shape:Array) {
		var _graphicName:String = "menus/selectorTerrain.swf";

		for (var i = 0; i < p_shape.length; i++) {
			var _currentX:Number = p_tile.getX() + p_shape[i][0];
			var _currentY:Number = p_tile.getY() + p_shape[i][1];
			
			var _xLocation:Number = pixelToTileX(_currentX);
			var _yLocation:Number = pixelToTileY(_currentY);	
			var _depth:Number = _selectorTargetDepth + (_currentY * _mapWidth) + _currentX;
			
			trace("CurX " + _currentX + " CurY " + _currentY);
			
			if (this._mapArray[_currentX][_currentY].getCounter() == -1) {
				this._mapArray[_currentX][_currentY].setIsTarget(true);
				Graphics.loadAndDrawObject("selectorTarget" + _depth , _depth, _graphicName, _xLocation, _yLocation);
			}
		}
	}
	
	
	public function removeSelectorTargets():Void {
		var _depth:Number;
		
		for (var i = 0; i < this._mapWidth; i++) {
			for (var j = 0; j < this._mapHeight; j++) {
				_depth = _selectorTargetDepth + (j * this._mapWidth) + i;	// create depth
				
				if (_root["selectorTarget" + _depth]) {
					this._mapArray[i][j].setIsTarget(false);
					removeMovieClip("selectorTarget" + _depth);
				}
			}
		}
	}
	
	public function removeSelector():Void {
		removeMovieClip("selector");
	}
}